
const ExecutionContext = require('./ExecutionContext');
const ExecutionContextStack = require('./ExecutionContextStack');
const ObjectEnvironmentRecords = require('./ObjectEnvironmentRecords');
const LexicalEnvironment = require('./LexicalEnvironment');
const FunctionInstance = require('./FunctionInstance');
const DeclarativeEnvironmentRecords = require('./DeclarativeEnvironmentRecords');
function NewDeclarativeEnvironment(outerLexicalEnvironment) {
    let envRec = new DeclarativeEnvironmentRecords();//里面不包含任何的变量绑定
    let env = new LexicalEnvironment(envRec, outerLexicalEnvironment);
    return env;
}

const ECStack = new ExecutionContextStack();
//1.全局准备阶段
//先创建环境记录项 负责登记全局变量,放的就是我们window或者 说全局变量
//global对象里的都会成为环境记录里的变量
let globalEnvironmentRecords = new ObjectEnvironmentRecords(global);
//先创建一个全局的词法环境 主要是用来登记变量和查找变量的
let globalLexicalEnvironment = new LexicalEnvironment(globalEnvironmentRecords, null);
//对于全局上下文对象来说，它的this =global
let globalExecutionContext = new ExecutionContext(globalLexicalEnvironment, global);
ECStack.push(globalExecutionContext);

//2.进入全局的编译阶段 进入变量登记阶段
//当我说到当前的执行上下文的时候就指栈顶正在活动中执行上下文
ECStack.current.lexicalEnvironment.createBinding('a');
ECStack.current.lexicalEnvironment.setBinding('a', undefined);
//登记函数one 函数的变量，作用域是由定义的时候决定
//静态作用域 函数的作用域是由在哪里定义决定的，不是在执行决定的 静态作用域
//变量提升完成了
let oneFn = new FunctionInstance('one', 'var b = 2;console.log(a, b);',
    ECStack.current.lexicalEnvironment);//globalLexicalEnvironment
ECStack.current.lexicalEnvironment.createBinding('one');
ECStack.current.lexicalEnvironment.setBinding('one', oneFn);
//执行全局代码
ECStack.current.lexicalEnvironment.setBinding('a', 1);

//开始执行函数one
let oneLexicalEnvironment = NewDeclarativeEnvironment(oneFn.scope);
let oneExecutionContext = new ExecutionContext(oneLexicalEnvironment, global);
ECStack.push(oneExecutionContext);

//开始one的编译阶段要登记one函数内的变量
ECStack.current.lexicalEnvironment.createBinding('b');
ECStack.current.lexicalEnvironment.setBinding('b', undefined);
//进入one的执行阶段
ECStack.current.lexicalEnvironment.setBinding('b', 2);
debugger
console.log(
    ECStack.current.lexicalEnvironment.GetIdentifierReference('a'),
    ECStack.current.lexicalEnvironment.GetIdentifierReference('b')
);





